#include <klib.h>
#include <klib-macros.h>
#include <stdint.h>

#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)

size_t strlen(const char *s) {
  size_t len = 0;

  while (s[len] != '\0') len++;

  return len;
}

char *strcpy(char *dst, const char *src) {
  int i;
  for (i = 0; src[i] != '\0'; i++) {
      dst[i] = src[i];
  }
  dst[i] = '\0';

  return dst;
}

char *strncpy(char *dst, const char *src, size_t n) {
  panic("Not implemented");
}

char *strcat(char *dst, const char *src) {
  int i = 0;
  while (dst[i] != '\0')  i++;

  for (int j = 0; src[j] != '\0'; j++) {
    dst[i++] = src [j];
  }

  dst[i] = '\0';

  return dst;
}

int strcmp(const char *s1, const char *s2) {
  int ret = 0;

  for (int i = 0; s1[i] != '\0' || s2[i] != '\0'; i++) {
    ret = s1[i] - s2[i];
    if (ret != 0) break;
  }

  return ret;
}

int strncmp(const char *s1, const char *s2, size_t n) {
  int ret = 0;

  for (int i = 0; i < n && (s1[i] != '\0' || s2[i] != '\0'); i++) {
    ret = s1[i] - s2[i];
    if (ret != 0) break;
  }

  return ret;
}

void *memset(void *s, int c, size_t n) {
  char *dest = (char *)s;

  for (int i = 0; i < n; i++) {
    dest[i] = c;
  }

  return (void *)dest;
}

void *memmove(void *dst, const void *src, size_t n) {
  void *src1 = malloc(n);

  memcpy(src1, src, n);
  memcpy(dst, src1, n);

  return dst;
}

void *memcpy(void *out, const void *in, size_t n) {
  char *src = (char *) in;
  char *dest = (char *) out;

  for (int i = 0; i < n; i++) {
    *(dest + i) = *(src + i);
  }

  return (void *)dest;
}

int memcmp(const void *s1, const void *s2, size_t n) {
  int ret = 0;
  char *str1 = (char *)s1;
  char *str2 = (char *)s2;

  for (int i = 0; i < n; i++) {
    ret = str1[i] - str2[i];
    if (ret != 0) break;
  }

  return ret;
}

#endif
